﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Collections.Generic;

using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Symbols;
using ESRI.ArcGIS.Client.Tasks;
using ESRI.ArcGIS.Client.Toolkit;

using Microsoft.Surface;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;
using Microsoft.Surface.Presentation.Input;

namespace eGrid_App
{
    /// <summary>
    /// This class represents the scatterview item which will hold the map.
    /// It includes the frame of the map with the toolbar buttons and the actions of these buttons.
    /// Inside of the frame is the actual map control.
    /// </summary>
    public partial class MapFrame : ScatterViewItem
    {
        private ScatterLayer tpScatterView;
        private Bookmark bookmark;
        private GhostFrame linkedGhostFrame;
        private int _id;        

        public int ID
        {
            get
            {
                return _id;
            }
        }

        public Bookmark RelatedBookmark
        {
            get
            {
                return bookmark;
            }
            set
            {
                bookmark = value;
            }
        }

        # region Constructors and Initializations

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mainView"></param>
        /// <param name="relatedGhostFrame"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        public MapFrame(ScatterLayer mainView, GhostFrame relatedGhostFrame, MapPoint p1, MapPoint p2)
        {
            InitializeComponent();

            tpScatterView = mainView;
                        
            linkedGhostFrame = relatedGhostFrame;
            linkedGhostFrame.LinkedMapFrame = this;

            MainMap.Map.Loaded += new RoutedEventHandler(MainMap_Loaded);

            // Initialize the map
            InitializeMap();
            LoadMap(p1, p2);
            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mainView"></param>
        /// <param name="relatedGhostFrame"></param>
        /// <param name="env"></param>
        /// <param name="color"></param>
        public MapFrame(ScatterLayer mainView, GhostFrame relatedGhostFrame, Envelope env, SolidColorBrush color)
        {
            InitializeComponent();

            tpScatterView = mainView;
                        
            linkedGhostFrame = relatedGhostFrame;
            linkedGhostFrame.LinkedMapFrame = this;

            glassFrame1.Background = color;
            glassFrame2.Background = color;
            glassFrame3.Background = color;
            glassFrame4.Background = color;

            MainMap.Map.Loaded += new RoutedEventHandler(MainMap_Loaded);

            // Initialize the map
            InitializeMap();
            LoadMap(env);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mainView"></param>
        /// <param name="relatedGhostFrame"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="color"></param>
        public MapFrame(ScatterLayer mainView, GhostFrame relatedGhostFrame, MapPoint p1, MapPoint p2, SolidColorBrush color)
        {
            InitializeComponent();

            tpScatterView = mainView;
                        
            linkedGhostFrame = relatedGhostFrame;
            linkedGhostFrame.LinkedMapFrame = this;

            glassFrame1.Background = color;
            glassFrame2.Background = color;
            glassFrame3.Background = color;
            glassFrame4.Background = color;

            MainMap.Map.Loaded += new RoutedEventHandler(MainMap_Loaded);

            // Initialize the map
            InitializeMap();
            LoadMap(p1, p2);
        }

        # endregion

        #region Delegations for Map Layer Changes

        public void MapLayerAdded(Layer addLayer)
        {
            Layer clone = MapLayersManager.Instance.CloneLayer(addLayer);
            if (clone != null)
                MainMap.AddMapLayer(clone);
        }

        public void MapLayerDeleted(Layer deleteLayer)
        {
            MainMap.RemoveMapLayer(deleteLayer);
        }

        #endregion

        # region Other Members

        /// <summary>
        /// Loads an image - for the buttons.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private static Image LoadImageFromPath(string path)
        {
            ImageSourceConverter converter = new ImageSourceConverter();
            Image image = new Image();

            BitmapImage bitMapImage = new BitmapImage();
            bitMapImage.BeginInit();
            bitMapImage.UriSource = new Uri(path, UriKind.Relative);
            bitMapImage.EndInit();
            image.Stretch = Stretch.Fill;
            image.Source = bitMapImage;
            return image;
        }

        /// <summary>
        /// This button is supposed to save the changes done in the map.
        /// Currently it closes the frame and save the position of the frame to
        /// Bookmark object ONLY.        
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ArchiveButton_Click(object sender, RoutedEventArgs e)
        {
            if (bookmark != null)
            {
                bookmark.MapFrameEnvelope = MainMap.Map.Extent;
                bookmark.MapFrameWidth = this.Width;
                bookmark.MapFrameHeight = this.Height;
                bookmark.MapFramePreviouslyOpen = true;
                bookmark.MapFrameCurrentlyOpen = false;
                bookmark.MapFrameCenter = this.Center;
                bookmark.MapFrameOrientation = this.Orientation;
            }

            this.tpScatterView.RemoveMap(this);
        }

        public void SetMapFrameName(string name)
        {
            MapFrameTitle.Text = name;
        }

        public GhostFrame GetGhostFrame()
        {
            return linkedGhostFrame;
        }

        private void MapLayersButton_Click(object sender, RoutedEventArgs e)
        {
            if (MainMap.ShowLayersList)
            {
                MainMap.ShowLayersList = false;
            }
            else
            {
                MainMap.ShowLayersList = true;
            }

        }

        private void RefreshMapButton_Click(object sender, RoutedEventArgs e)
        {
            MainMap.ReloadMap();
        }


        # endregion

        # region ArcGisMap Functions
        
        /// <summary>
        /// Initialize the map
        /// </summary>
        private void InitializeMap()
        {
            MainMap.setLinkedGhostFrame(linkedGhostFrame);
            MainMap.MapWidth = MainMap.Width;
            MainMap.MapHeight = MainMap.Height;
            MainMap.ShowLayersList = false;            
        }


        private void LoadMap(Envelope env)
        {
            MainMap.setExtentFromEnvelop(env);
        }

        private void LoadMap(MapPoint p1, MapPoint p2)
        {
            Envelope env = new Envelope(p1, p2);
            MainMap.setExtentFromEnvelop(env);
            //MainMap.setExtentFromLtdLng(p1.Y, p1.X);
        }


        private void MainMap_Loaded(object sender, RoutedEventArgs e)
        {
            linkedGhostFrame.UpdatePosition(MainMap.Map.Extent);
        }

        # endregion
        
        
        # region scalling

        /// <summary>
        /// Changing the size of the map
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ScatterViewItem_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (e.PreviousSize.Height == 0)
                return;
                        
            // Resize the map grid
            MainMap.Width += e.NewSize.Width - e.PreviousSize.Width;
            MainMap.Height += e.NewSize.Height - e.PreviousSize.Height;
            linkedGhostFrame.UpdatePosition(MainMap.Extent);
        }

        # endregion scalling

        # region Map_Graphics


        private void DrawPointButton_Click(object sender, RoutedEventArgs e)
        {
            MainMap.SetDrawPointMode();
        }

        private void DrawPolylineButton_Click(object sender, RoutedEventArgs e)
        {
            MainMap.SetDrawPolylineMode();
        }

        private void DrawPolygonButton_Click(object sender, RoutedEventArgs e)
        {
            MainMap.SetDrawPolygonMode();
        }

        private void DrawRectangleButton_Click(object sender, RoutedEventArgs e)
        {
            MainMap.SetDrawRectangleMode();
        }

        private void DrawFreehandButton_Click(object sender, RoutedEventArgs e)
        {
            MainMap.SetDrawFreehandMode();
        }

        private void StopDrawButton_Click(object sender, RoutedEventArgs e)
        {
            MainMap.StopDrawing();
        }

        private void ClearGraphicsButton_Click(object sender, RoutedEventArgs e)
        {
            MainMap.ClearGraphics();
        }

        # endregion Map_Graphics

        # region Events on Map

        /// <summary>
        ///
        /// This handles the event when a touch lands on top
        /// of ArcGisMap not the scatterviewitem frame, we
        /// mark the event as handled to prevent it from
        /// bubbling up to the scatterviewitem such that
        /// scatterviewitem will not have a chance to 
        /// handle this touch event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainMap_TouchDown(object sender, TouchEventArgs e)
        {
            
            if(sender is ArcGisMap) e.Handled = true;
        }

        /// <summary>
        /// This handles the touch event when the touch is moving
        /// on top of ArcGisMap, we mark this as handled so that
        /// the scaterviewitem container will not receive this
        /// event.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainMap_TouchMove(object sender, TouchEventArgs e)
        {
            if(sender is ArcGisMap) e.Handled = true;
        }

        /// <summary>
        /// This handles the touch event when a touch is lifted
        /// on top of ArcGisMap, we mark it as handled so that
        /// the scatterviewitem container will not received this 
        /// event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainMap_TouchUp(object sender, TouchEventArgs e)
        {
            if(sender is ArcGisMap) e.Handled = true;            
        }

        # endregion

        public void UpdateMap(Envelope mapEnv)
        {
            MainMap.setExtentFromEnvelop(mapEnv);
        }


    }
}
